package com.kids.movies.streaming;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnSeekCompleteListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.StrictMode;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.ToggleButton;

import com.englishsong.nurseryrhymes.R;
import com.kids.movies.E4KidsConfig;
import com.kids.movies.util.Debug;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@SuppressLint("NewApi")
public class MainActivity extends Activity implements OnPreparedListener,
		OnErrorListener {

	private String TAG = getClass().getSimpleName();
	private ImageButton stop, fullScreen, forward, reward;
	private ToggleButton playtogglebutton, repeat;
	private TextView timeEnd, timeElapsed, title;
	private ProgressBar loading;
	private SeekBar seekBar;
	private MyVideoView videoviewer;
	private CountDownTimer timer;
	private int mVideoWidth, mVideoHeight;
	private String sTitle;
	private RelativeLayout playerToolbar;
	public boolean isOntouch = false;
	private Handler handler;
	private Runnable runnable;
	private String[] sUrl;
	private int iCurrentPlayIndexUrl = -1;
    private String linkVideo;
    private String idVideo;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		setContentView(R.layout.player_contol_wheel_view);

		FrameLayout mControlContainer = (FrameLayout) findViewById(R.id.player_control);
		mControlContainer.addView((View) new PlayerControlWheelVideo(
				getApplicationContext()));

		loading = (ProgressBar) findViewById(R.id.loading);

		stop = (ImageButton) findViewById(R.id.player_overlay_stop);
		fullScreen = (ImageButton) findViewById(R.id.player_overlay_size);
		forward = (ImageButton) findViewById(R.id.player_overlay_forward);
		reward = (ImageButton) findViewById(R.id.player_overlay_backward);
		repeat = (ToggleButton) findViewById(R.id.player_overlay_repeat);
		playtogglebutton = (ToggleButton) findViewById(R.id.playtogglebutton);
		timeElapsed = (TextView) findViewById(R.id.player_overlay_time);
		timeEnd = (TextView) findViewById(R.id.player_overlay_length);
		seekBar = (SeekBar) findViewById(R.id.player_overlay_seekbar);
		title = (TextView) findViewById(R.id.player_overlay_title);
		videoviewer = (MyVideoView) findViewById(R.id.videoviewer);
		playerToolbar = (RelativeLayout) findViewById(R.id.playertoolbar);
		Bundle bundle = getIntent().getExtras();
		if(bundle != null)
		{
		    linkVideo = bundle.getString(E4KidsConfig.KEY_INTENT_LINK);
		    idVideo = bundle.getString(E4KidsConfig.KEY_INTENT_VID);
		    
		    Debug.debug("Link Video : " + linkVideo);
		}
		StringBuilder stringBuilder = new StringBuilder("http://www.")
		.append("youtube.com/watch?v=").append(linkVideo);
		String namevideo=stringBuilder.toString();
		sUrl = new String[] { namevideo,""};



		sUrl[0] = UtilVideo.buildYoutubeUrl(sUrl[0]);

		iCurrentPlayIndexUrl = 1;
		videoviewer.isLoop = false;

		videoviewer.setVideoURI(Uri.parse(sUrl[0]));
		videoviewer.requestFocus();
		videoviewer.setKeepScreenOn(true);
		videoviewer.setOnErrorListener(this);
		videoviewer.setOnPreparedListener(this);
		videoviewer.changeVideoSize(mVideoWidth, mVideoHeight);

		if (sTitle != null && sTitle.equals("")) {
			sTitle = getFileNameFromUrl(sUrl[0]);
		}

		title.setText(sTitle);

		handler = new Handler();
		runnable = new Runnable() {
			@Override
			public void run() {
				/* do what you need to do */
				playerToolbar.setVisibility(View.INVISIBLE);
				/* and here comes the "trick" run */

			}
		};

		handler.postDelayed(runnable, 5000);

		videoviewer.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				playerToolbar.setVisibility(View.VISIBLE);
				handler.removeCallbacks(runnable);
				if (event.getAction() == MotionEvent.ACTION_UP) {
					handler.postDelayed(runnable, 5000);
				}
				return true;
			}
		});

	}

	private OnSeekBarChangeListener seekbarChangelistener = new OnSeekBarChangeListener() {

		@Override
		public void onStopTrackingTouch(SeekBar seekBar) {

		}

		@Override
		public void onStartTrackingTouch(SeekBar seekBar) {
		}

		@Override
		public void onProgressChanged(SeekBar seekBar, int progress,
				boolean fromUser) {
			if (fromUser) {
				Log.e("onProgressChanged: ", Integer.toString(progress));
				float b = videoviewer.getDuration();
				int pos = (int) (b * progress / 100);
				videoviewer.seekTo(pos);
				Log.i(TAG, "Touch Pos: " + pos);
				timeElapsed
						.setText(countTime(videoviewer.getCurrentPosition()));
				playMedia(true);
			}

			if (progress == seekBar.getMax() && !videoviewer.isLoop) {
				System.out.println("inside the setOnSeekCompleteListener");
				// videoviewer.stopPlayback();
				stopMedia();
				if (sUrl.length > 1 && iCurrentPlayIndexUrl < sUrl.length - 1) {
					iCurrentPlayIndexUrl++;
					sUrl[iCurrentPlayIndexUrl] = UtilVideo
							.buildYoutubeUrl(sUrl[iCurrentPlayIndexUrl]);
					videoviewer.setVideoURI(Uri
							.parse(sUrl[iCurrentPlayIndexUrl]));
					videoviewer.requestFocus();
					videoviewer.setKeepScreenOn(true);
					videoviewer.changeVideoSize(mVideoWidth, mVideoHeight);
					playMedia(true);
				}
			} else {
				playMedia(true);
			}
			System.out.println("inside------ the setOnSeekCompleteListener");

		}
	};

	public String getFileNameFromUrl(String path) {
		String[] pathArray = path.split("/");
		return pathArray[pathArray.length - 1];
	}

	private OnClickListener stoplistener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			stopMedia();
		}
	};

	private OnClickListener fullScreenlistener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			if (videoviewer.isFullScreen)
				videoviewer.isFullScreen = false;
			else
				videoviewer.isFullScreen = true;
			videoviewer.changeVideoSize(mVideoWidth, mVideoHeight);
		}
	};

	private OnClickListener loopinglistener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			if (videoviewer.isLoop)
				videoviewer.isLoop = false;
			else
				videoviewer.isLoop = true;
		}
	};

	private OnCheckedChangeListener checkedchangelistener = new OnCheckedChangeListener() {

		@Override
		public void onCheckedChanged(CompoundButton arg0, boolean isChecked) {
			/* pause player */
			if (isChecked) {
				System.out.println("player pause");
				playMedia(false);
			}
			/* play player */
			else {
				System.out.println("player play");
				playMedia(true);
			}
		}
	};

	private View.OnClickListener mFfwdListener = new View.OnClickListener() {
		public void onClick(View v) {
			int pos = videoviewer.getCurrentPosition();
			pos += 2000; // milliseconds
			videoviewer.seekTo(pos);
			timeElapsed.setText(countTime(videoviewer.getCurrentPosition()));
			float a = videoviewer.getCurrentPosition();
			float b = videoviewer.getDuration();
			seekBar.setProgress((int) (a / b * 100));
			playMedia(true);
		}
	};

	private View.OnClickListener mRewListener = new View.OnClickListener() {
		public void onClick(View v) {
			int pos = videoviewer.getCurrentPosition();
			pos -= 2000; // milliseconds
			videoviewer.seekTo(pos);
			timeElapsed.setText(countTime(videoviewer.getCurrentPosition()));
			float a = videoviewer.getCurrentPosition();
			float b = videoviewer.getDuration();
			seekBar.setProgress((int) (a / b * 100));
			playMedia(true);
		}
	};

	@Override
	public boolean onError(MediaPlayer mp, int what, int extra) {
		// loading.hide();
		loading.setVisibility(View.GONE);
		return false;
	}

	@Override
	public void onPrepared(MediaPlayer mp) {
		Log.d(TAG, "media player preparing.......");

		if (videoviewer.isLoop)
			mp.setLooping(true);
		else
			mp.setLooping(false);

		// loading.hide();
		playtogglebutton.setOnCheckedChangeListener(checkedchangelistener);
		stop.setOnClickListener(stoplistener);
		fullScreen.setOnClickListener(fullScreenlistener);
		repeat.setOnClickListener(loopinglistener);
		forward.setOnClickListener(mFfwdListener);
		reward.setOnClickListener(mRewListener);
		seekBar.setOnSeekBarChangeListener(seekbarChangelistener);

		loading.setVisibility(View.GONE);

		mVideoWidth = mp.getVideoWidth();
		mVideoHeight = mp.getVideoHeight();
		// onVideoSizeChangedListener declaration
		mp.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {

			@Override
			public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
				Log.d(TAG, "onVideoSizeChanged called " + width + ":" + height);
				if (width == 0 || height == 0) {
					Log.e(TAG, "invalid video width(" + width + ") or height("
							+ height + ")");
					return;
				}
				mVideoWidth = width;
				mVideoHeight = height;
				playMedia(true);
			}
		});

		// onSeekCompletionListener declaration
		mp.setOnSeekCompleteListener(new OnSeekCompleteListener() {
			// show current frame after changing the playback position
			@Override
			public void onSeekComplete(MediaPlayer mp) {

			}
		});

		mp.setOnCompletionListener(null);
		// onBufferingUpdateListener declaration
		mp.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
			// show updated information about the buffering progress
			@Override
			public void onBufferingUpdate(MediaPlayer mp, int percent) {
				Log.d(this.getClass().getName(), "percent: " + percent);
				seekBar.setSecondaryProgress(percent);
			}
		});

		int time = videoviewer.getDuration();
		int time_elapsed = videoviewer.getCurrentPosition();
		seekBar.setProgress(time_elapsed);

		// update current playback time every 500ms until stop
		timer = new CountDownTimer(time, 500) {

			@Override
			public void onTick(long millisUntilFinished) {
				timeElapsed
						.setText(countTime(videoviewer.getCurrentPosition()));
				float a = videoviewer.getCurrentPosition();
				float b = videoviewer.getDuration();
				seekBar.setProgress((int) (a / b * 100));
			}

			@Override
			public void onFinish() {
				stopMedia();
			}
		};

		timeEnd.setText(countTime(time));
		timeElapsed.setText(countTime(time_elapsed));
		playMedia(true);
	}

	/**
	 * Convert time from milliseconds into minutes and seconds, proper to media
	 * player
	 * 
	 * @param miliseconds
	 *            media content time in milliseconds
	 * @return time in format minutes:seconds
	 */
	public String countTime(int miliseconds) {
		String timeInMinutes = new String();
		int minutes = miliseconds / 60000;
		int seconds = (miliseconds % 60000) / 1000;
		timeInMinutes = minutes + ":"
				+ (seconds < 10 ? "0" + seconds : seconds);
		return timeInMinutes;
	}

	/**
	 * Start or Pause playback of media content
	 * 
	 * @param v
	 *            View the touch event has been dispatched to
	 */
	public void playMedia(boolean isplay) {
		System.err.println("height:- " + mVideoHeight);
		System.err.println("width:- " + mVideoWidth);
		if (isplay) {
			videoviewer.changeVideoSize(mVideoWidth, mVideoHeight);
			videoviewer.start();
			timer.start();
		} else {
			videoviewer.pause();
			timer.cancel();
		}

	}

	/**
	 * Pause and rewind to beginning of the media content
	 * 
	 * @param v
	 *            View the touch event has been dispatched to
	 */
	public void stopMedia() {
		if (videoviewer.getCurrentPosition() != 0) {

			playtogglebutton.setChecked(true);

			videoviewer.pause();
			videoviewer.seekTo(0);
			timer.cancel();

			timeElapsed.setText(countTime(videoviewer.getCurrentPosition()));
			seekBar.setProgress(0);
		}
	}

	@Override
	protected void onStop() {
		if (videoviewer != null)
			videoviewer.stopPlayback();
		if (timer != null) {
			timer.cancel();
		}
		super.onStop();
	}

	/**
	 * Calculate the YouTube URL to load the video. Includes retrieving a token
	 * that YouTube requires to play the video.
	 * 
	 * @param pYouTubeFmtQuality
	 *            quality of the video. 17=low, 18=high
	 * @param bFallback
	 *            whether to fallback to lower quality in case the supplied
	 *            quality is not available
	 * @param pYouTubeVideoId
	 *            the id of the video
	 * @return the url string that will retrieve the video
	 * @throws IOException
	 * @throws ClientProtocolException
	 * @throws UnsupportedEncodingException
	 */
	@TargetApi(Build.VERSION_CODES.GINGERBREAD)
	@SuppressLint("NewApi")
	public static String calculateYouTubeUrl(String pYouTubeFmtQuality,
			boolean pFallback, String pYouTubeVideoUrl) throws IOException,
			ClientProtocolException, UnsupportedEncodingException {

		StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
				.permitAll().build();

		StrictMode.setThreadPolicy(policy);

		String lUriStr = null;
		HttpClient lClient = new DefaultHttpClient();

		HttpGet lGetMethod = new HttpGet(pYouTubeVideoUrl);

		HttpResponse lResp = null;

		lResp = lClient.execute(lGetMethod);

		ByteArrayOutputStream lBOS = new ByteArrayOutputStream();
		String lInfoStr = null;

		lResp.getEntity().writeTo(lBOS);
		lInfoStr = new String(lBOS.toString("UTF-8"));

		String[] lArgs = lInfoStr.split("&");
		Map<String, String> lArgMap = new HashMap<String, String>();
		for (int i = 0; i < lArgs.length; i++) {
			String[] lArgValStrArr = lArgs[i].split("=");
			if (lArgValStrArr != null) {
				if (lArgValStrArr.length >= 2) {
					lArgMap.put(lArgValStrArr[0],
							URLDecoder.decode(lArgValStrArr[1]));
				}
			}
		}

		// Find out the URI string from the parameters

		// Populate the list of formats for the video
		String lFmtList = URLDecoder.decode(lArgMap.get("fmt_list"));
		ArrayList<VideoFormat> lFormats = new ArrayList<VideoFormat>();
		if (null != lFmtList) {
			String lFormatStrs[] = lFmtList.split(",");

			for (String lFormatStr : lFormatStrs) {
				VideoFormat lFormat = new VideoFormat(lFormatStr);
				lFormats.add(lFormat);
			}
		}

		// Populate the list of streams for the video
		String lStreamList = lArgMap.get("url_encoded_fmt_stream_map");
		if (null != lStreamList) {
			String lStreamStrs[] = lStreamList.split(",");
			ArrayList<VideoStream> lStreams = new ArrayList<VideoStream>();
			for (String lStreamStr : lStreamStrs) {
				VideoStream lStream = new VideoStream(lStreamStr);
				lStreams.add(lStream);
			}

			// Search for the given format in the list of video formats
			// if it is there, select the corresponding stream
			// otherwise if fallback is requested, check for next lower format
			int lFormatId = Integer.parseInt(pYouTubeFmtQuality);

			VideoFormat lSearchFormat = new VideoFormat(lFormatId);
			while (!lFormats.contains(lSearchFormat) && pFallback) {
				int lOldId = lSearchFormat.getId();
				int lNewId = getSupportedFallbackId(lOldId);

				if (lOldId == lNewId) {
					break;
				}
				lSearchFormat = new VideoFormat(lNewId);
			}

			int lIndex = lFormats.indexOf(lSearchFormat);
			if (lIndex >= 0) {
				VideoStream lSearchStream = lStreams.get(lIndex);
				lUriStr = lSearchStream.getUrl();
			}

		}
		// Return the URI string. It may be null if the format (or a fallback
		// format if enabled)
		// is not found in the list of formats for the video
		return lUriStr;
	}

	public static int getSupportedFallbackId(int pOldId) {
		final int lSupportedFormatIds[] = { 13, // 3GPP (MPEG-4 encoded) Low
												// quality
				17, // 3GPP (MPEG-4 encoded) Medium quality
				18, // MP4 (H.264 encoded) Normal quality
				22, // MP4 (H.264 encoded) High quality
				37 // MP4 (H.264 encoded) High quality
		};
		int lFallbackId = pOldId;
		for (int i = lSupportedFormatIds.length - 1; i >= 0; i--) {
			if (pOldId == lSupportedFormatIds[i] && i > 0) {
				lFallbackId = lSupportedFormatIds[i - 1];
			}
		}
		return lFallbackId;
	}

	public static String getUrlVideoRTSP(String urlYoutube) {
		try {
			String gdy = "http://gdata.youtube.com/feeds/api/videos/";
			DocumentBuilder documentBuilder = DocumentBuilderFactory
					.newInstance().newDocumentBuilder();
			String id = extractYoutubeId(urlYoutube);
			URL url = new URL(gdy + id);
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();
			Document doc = documentBuilder.parse(connection.getInputStream());
			Element el = doc.getDocumentElement();
			NodeList list = el.getElementsByTagName("media:content");// /media:content
			String cursor = urlYoutube;
			for (int i = 0; i < list.getLength(); i++) {
				Node node = list.item(i);
				if (node != null) {
					NamedNodeMap nodeMap = node.getAttributes();
					HashMap<String, String> maps = new HashMap<String, String>();
					for (int j = 0; j < nodeMap.getLength(); j++) {
						Attr att = (Attr) nodeMap.item(j);
						maps.put(att.getName(), att.getValue());
					}
					if (maps.containsKey("yt:format")) {
						String f = maps.get("yt:format");
						if (maps.containsKey("url")) {
							cursor = maps.get("url");
						}
						if (f.equals("1"))
							return cursor;
					}
				}
			}
			return cursor;
		} catch (Exception ex) {
			Log.e("Get Url Video RTSP Exception======>>", ex.toString());
		}
		return urlYoutube;

	}

	protected static String extractYoutubeId(String url)
			throws MalformedURLException {
		String id = null;
		try {
			String query = new URL(url).getQuery();
			if (query != null) {
				String[] param = query.split("&");
				for (String row : param) {
					String[] param1 = row.split("=");
					if (param1[0].equals("v")) {
						id = param1[1];
					}
				}
			} else {
				if (url.contains("embed")) {
					id = url.substring(url.lastIndexOf("/") + 1);
				}
			}
		} catch (Exception ex) {
			Log.e("Exception", ex.toString());
		}
		return id;
	}

}